/**
 * 公共工具类
 * 作者：xc
 * 版本：1.0.0
 */
export class CommonTool {
  /**
   * 非空返回true
   * 参数： str 效验支付串
   */
  static notNull(str) {
    if (str === undefined) {
      return false;
    } else if (str === null) {
      return false;
    } else if (str === '') {
      return false;
    } else if (typeof str === 'object') {
      if (Object.keys(str).length === 0) {
        return false;
      }
    }
    return true;
  }

  /**
   * 给指定字段写入数据
   *
   * 参数： data 数据对象
   * 参数： field 操作的字段(.[index].)代表数组，index数组表
   * 参数： value 要替换的值
   */
  static setObjectField(data, field, value) {
    if (value === undefined || value === null) {
      console.error('传入的value不能为空,检测配置是否正确!');
      return {};
    }
    if (field === undefined || field === null) {
      console.error('传入的field不能为空,检测配置是否正确!');
      return {};
    }
    let str = '';
    let str1 = '';
    const fields = field.split('.');
    for (let i = 0; i < fields.length; i++) {
      const char = fields[i].split('');
      if (char[0] === '[' && char[char.length - 1] === ']') {
        const length = parseFloat(fields[i].split('[')[1].split(']')[0]);
        str = str + '[';
        for (let j = 0; j < length; j++) {
          if (j !== length) {
            str = str + '{},';
          }
        }
        if (i === fields.length - 1) {
          str = str + JSON.stringify(value) + ']';
        } else {
          str1 = str1 + ']';
        }
      } else {
        if (i === fields.length - 1) {
          str = str + '{"' + fields[i] + '":' + JSON.stringify(value);
          str1 = str1 + '}';
        } else {
          str = str + '{"' + fields[i] + '":';
          str1 = str1 + '}';
        }
      }
    }
    const obj = JSON.parse(str + str1.split('').reverse().join(''));
    if (obj instanceof Array) {
      obj.forEach((ref, index) => {
        data[index] = ref;
      });
      return data;
    } else {
      return this.deepMerge(data, obj);
    }

  }

  /**
   * 深度合并对象对像
   * 参数： data
   * 参数： obj
   */
  static deepMerge(data, obj) {
    const array = Object.getOwnPropertyNames(obj);
    for (const key of array) {
      if (!CommonTool.notNull(obj[key])) {
        continue;
      }
      if (data[key] instanceof Array && obj[key] instanceof Array) {
        for (let i = 0; i < obj[key].length; i++) {
          if (CommonTool.notNull(data[key][i]) && data[key][i].toString() === '[object Object]') {
            data[key][i] = this.deepMerge(data[key][i], obj[key][i]);
          } else {
            if (JSON.stringify(obj[key][i]) !== '{}') {
              data[key][i] = obj[key][i];
            }
          }
        }
      } else if (data[key] instanceof Array) {
        data[key] = obj[key];
      } else if (CommonTool.notNull(data[key]) && data[key].toString() === '[object Object]') {
        this.deepMerge(data[key], obj[key]);
      } else {
        data[key] = obj[key];
      }
    }
    return data;
  }

  /**
   * 获取指定字段的数据
   * 参数： data 数据
   * 参数： field 数据的那个属性
   */
  static getObjectField(data, field) {
    let obj;
    const fields = field.split('.');
    for (let i = 0; i < fields.length; i++) {
      if (i === 0) {
        obj = data[fields[i]];
      } else {
        if (CommonTool.notNull(obj)) {
          obj = obj[fields[i]];
        }
      }
    }
    return obj;
  }

  /**
   * 获取指定字段的数据，没有返回空串
   * 参数： data 数据
   * 参数： field 数据的那个属性
   */
  static conversion(data, field) {
    const obj = CommonTool.getObjectField(data, field);
    if (CommonTool.notNull(obj)) {
      return obj;
    } else {
      return '';
    }
  }

  /**
   * 解析url,给url的{}符号替换成合适的数据
   * 参数：url url格式：/user/{userId}/name
   * 参数：data 数据格式：{userId:123456}
   * 返回: url字符串
   */
  static analysisUrl(url, data) {
    const array = Object.getOwnPropertyNames(data);
    array.forEach((key, index) => {
      url = url.replace('{' + key + '}', data[key]);
    });
    return url;
  }

  /**
   * 将data解析成字符串并且拼接url
   * 参数： url url地址
   * 参数：data 参数对象
   * 返回: url字符串
   */
  static analysisParam(url, data) {
    let param = '';
    let array = [];
    if (CommonTool.notNull(data)) {
      array = Object.getOwnPropertyNames(data);
    }
    for (let i = 0; i < array.length; i++) {
      const key = array[i];
      if (i !== 0) {
        if (CommonTool.notNull(data[key])) {
          param += '&';
        }
      }
      if (CommonTool.notNull(data[key])) {
        param += key + '=' + data[key];
      }
    }
    if (CommonTool.notNull(param)) {
      return url + '?' + param;
    } else {
      return url;
    }
  }

  /**
   * 获取URL地址后面的参数
   *  参数： url url地址
   */
  static getUrlParam(url) {
    const data = {};
    if (url.indexOf('?') !== -1) {
      const str = url.split('?')[1];
      const list = str.split('&');
      for (let i = 0; i < list.length; i++) {
        data[list[i].split('=')[0]] = unescape(list[i].split('=')[1]);
      }
    }
    return data;
  }

  /**
   * 获取Cookie
   * 参数：key 存入数据的key
   */
  static getCookie(key) {
    const name = key + '=';
    const decodedCookie = decodeURIComponent(document.cookie);
    const ca = decodedCookie.split(';');
    for (let i = 0; i < ca.length; i++) {
      let c = ca[i];
      while (c.charAt(0) === ' ') {
        c = c.substring(1);
      }
      if (c.indexOf(name) === 0) {
        return c.substring(name.length, c.length);
      }
    }
    return '';
  }

  /**
   * 写入Cookie
   * 参数： key 存入数据的key，必传
   * 参数： value 存入数据的值，必传
   * 参数： config
   *  expires 有效期，单位毫秒,默认:1800000
   *  path Cookie的路径,默认:/
   *  sameSite SameSite 有两个属性值，分别是 Strict 和 Lax,Strict:表明这个 cookie 在任何情况下都不可能作为第三方 cookie
   */
  static setCookie(key, value, config?) {
    let cookie = key + '=' + value + ';';
    if (config && config.expires) {
      const date = new Date();
      date.setTime(date.getTime() + config.expires);
      cookie = cookie + 'expires=' + date.toUTCString() + ';';
    }
    if (config && config.path) {
      cookie = cookie + 'path=' + config.path + ';';
    } else {
      cookie = cookie + 'path=/;';
    }
    if (config && config.sameSite) {
      cookie = cookie + 'sameSite=' + config.sameSite + ';';
    }
    document.cookie = cookie;
  }

  /**
   * 删除Cookie
   * 参数： key 数据的key，必传
   * 参数： config
   *  expires 有效期，单位毫秒,默认:1800000
   *  path Cookie的路径,默认:/
   *  sameSite SameSite 有两个属性值，分别是 Strict 和 Lax,Strict:表明这个 cookie 在任何情况下都不可能作为第三方 cookie
   */
  static deleteCookie(key, config?) {
    if (!config) {
      config = {};
    }
    config.expires = 1;
    const data = CommonTool.getCookie(key);
    CommonTool.setCookie(key, data, config);
  }

  /**
   * base64字符串转换为Blob对像
   * 参数： base64Data 数据
   * 返回： Blob对象
   */
  static dataURItoBlob(base64Data) {
    let byteString;
    byteString = CommonTool.base64Decode(base64Data);
    const ia = new Uint8Array(byteString.length);
    for (let i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ia]);
  }

  /**
   * Base64编码
   * 参数： data 编码的数据
   */
  static base64Encode(data) {
    return window.btoa(data);
  }

  /**
   * Base64解码
   * 参数： data base64编码后的数据
   */
  static base64Decode(data) {
    return window.atob(data);
  }

  /**
   * 图片转缩略图
   * 参数： base64Url 图片的base64编码
   * 参数： callback 回调返回缩略图地址
   * 参数： w 宽
   * 参数： h 高
   */
  static compressImage(base64Url, callback, w, h) {
    // 初始化数据
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    w = w || 0;
    h = h || 0;
    const im = new Image();
    im.onload = (e) => {
      let thit = {width: 0, height: 0};
      // @ts-ignore
      thit = e.currentTarget;
      // 为传入缩放尺寸用原尺寸
      if (!w) {
        w = thit.width;
      }
      if (!h) {
        h = thit.height;
      }
      // 以长宽最大值作为最终生成图片的依据
      if (w !== thit.width || h !== thit.height) {
        let ratio;
        if (w > h) {
          ratio = thit.width / w;
          h = thit.height / ratio;
        } else if (w === h) {
          if (thit.width > thit.height) {
            ratio = thit.width / w;
            h = thit.height / ratio;
          } else {
            ratio = thit.height / h;
            w = thit.width / ratio;
          }
        } else {
          ratio = thit.height / h;
          w = thit.width / ratio;
        }
      }
      // 以传入的长宽作为最终生成图片的尺寸
      if (w > h) {
        const offset = (w - h) / 2;
        canvas.width = canvas.height = w;
        ctx.drawImage(im, 0, offset, w, h);
      } else if (w < h) {
        const offset = (h - w) / 2;
        canvas.width = canvas.height = h;
        ctx.drawImage(im, offset, 0, w, h);
      } else {
        canvas.width = canvas.height = h;
        ctx.drawImage(im, 0, 0, w, h);
      }
      callback(canvas.toDataURL('image/png'));
    };
    im.src = base64Url;
    return canvas;
  }

  /**
   * 获取后缀
   */
  static getSuffix(name) {
    let suffix = '';
    if (CommonTool.notNull(name)) {
      suffix = name.substring(name.lastIndexOf('.'), name.length);
    }
    return suffix.toLowerCase();
  }


  /**
   * 获取文件空间转换
   */
  static getSpace(value) {
    if (value < 1024) {
      return value + 'b';
    } else if (value < 1048576) {
      return (value / 1024).toFixed(2) + 'kb';
    } else if (value < 1073741824) {
      return (value / 1048576).toFixed(2) + 'mb';
    } else if (value < 1099511627776) {
      return (value / 1073741824).toFixed(2) + 'gb';
    } else if (value < 1.1259e+15) {
      return (value / 1099511627776).toFixed(2) + 'tb';
    } else if (value < 1.1529e+18) {
      return (value / 1.1259e+15).toFixed(2) + 'pb';
    } else {
      return (value / 1.1529e+18).toFixed(2) + 'eb';
    }
  }

  /**
   * 获取文件空间转换带单位
   */
  static getSpaceUnit(value) {
    if (value < 1024) {
      return {value, unit: 'b'};
    } else if (value < 1048576) {
      return {value: (value / 1024).toFixed(2), unit: 'kb'};
    } else if (value < 1073741824) {
      return {value: (value / 1048576).toFixed(2), unit: 'mb'};
    } else if (value < 1099511627776) {
      return {value: (value / 1073741824).toFixed(2), unit: 'gb'};
    } else if (value < 1.1259e+15) {
      return {value: (value / 1099511627776).toFixed(2), unit: 'tb'};
    } else if (value < 1.1529e+18) {
      return {value: (value / 1.1259e+15).toFixed(2), unit: 'pb'};
    } else {
      return {value: (value / 1.1529e+18).toFixed(2), unit: 'eb'};
    }
  }

  /**
   * 字符串转
   */
  static turnDate(str) {
    if (typeof str === 'string') {
      return new Date(str.replace(/-/g, '/'));
    } else {
      return str;
    }
  }

  /**
   * 时间转换(注意大小写哦)
   * 参数 date 传入时间对象
   * 参数 fmt 转换后成什么格式的支付串,
   * Y:年,M:月,D:日 h:时,m:分,s:秒,q:季度,S:毫秒
   * 默认格式:YYYY-MM-DD hh:mm:ss
   */
  static dateFormat(date, fmt): string {
    if (!CommonTool.notNull(fmt)) {
      fmt = 'YYYY-MM-DD hh:mm:ss';
    }
    const o = {
      'M+': date.getMonth() + 1, // 月份
      'D+': date.getDate(), // 日
      'h+': date.getHours(), // 小时
      'm+': date.getMinutes(), // 分
      's+': date.getSeconds(), // 秒
      'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
      'S': date.getMilliseconds() // 毫秒
    };
    if (/(Y+)/.test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
    }
    for (const k in o) {
      if (new RegExp('(' + k + ')').test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
      }
    }
    return fmt;
  }

  /**
   * 生成随机数
   *  minNum 最小值
   *  maxNum 最大值
   */
  static randomNum(minNum, maxNum) {
    switch (arguments.length) {
      case 1:
        return parseInt('' + Math.random() * minNum + 1, 10);
        break;
      case 2:
        return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
        break;
      default:
        return 0;
        break;
    }
  }
}
